/**
 * @file map_database.cc
 * @author enic (errorcpp@qq.com)
 * @brief 
 * @version 0.1
 * @date 2022-02-21
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#include <cassert>
#include "map_database.hh"

namespace xstr {

class MapDatabase::NodeList
{
public:
    struct Node
    {
        Node* next;
        hash64_result_t hash;
        //std::size_t data_len;
        char* data;  // 有一种优化是省略data字段，默认Node指针+sizeof(Node)就是数据开始位置
    };

    /**
     * @brief 位置搜索结果
     */
    struct FindPlaceResult
    {
        Node* prev;   // 目标位置的上一个节点
        Node* tar;    // 目标位置
        Node* next;   // 目标位置的下一个节点
    };

public:
    NodeList() : head_(NULL)
    {}

    ~NodeList()
    {
        Node* cur = head_;
        while(NULL != cur)
        {
            Node* next = cur->next;
            free_node(cur);
            cur = next;
        }
    }

    BasicDatabase::InsertStatus 
        insert(hash64_result_t hash, const char* str, size_t cnt)
    {
        if(NULL == head_)
            head_ = malloc_node(hash, str);
            return BasicDatabase::InsertStatus::kNewString;
        Node* prev = NULL;
        Node* cur = head_;
        while(cur)
        {
            if(cur->hash >= hash)
                break;
            prev = cur;
        }
        Node* new_node = malloc_node(hash, str);
        Node* tar_node = prev ? prev : head_;
        if(tar_node->next && (tar_node->next->hash == hash))
            if(0 != strcmp(tar_node->next->data, str))
                return BasicDatabase::InsertStatus::kCollisison;
            else
                return BasicDatabase::InsertStatus::kOldString;
        new_node->next = tar_node->next;
        tar_node->next = new_node;
        return BasicDatabase::InsertStatus::kNewString;
    }

protected:
    Node* malloc_node(hash64_result_t hash, const char* str)
    {
        Node* node = new Node;
        node->next = NULL;
        if(NULL != str)
        {
            node->data = new char[strlen(str)];
            node->hash = hash;
        }
        return node;
    }

    void free_node(Node* node)
    {
        if(node)
        {
            if(node->data)
                delete node->data;
            delete node;
        }
    }

    /**
     * @brief  找到hash为指定值的节点
     * 
     * @param hash 给定的哈希值
     * @return Node*
     */
    Node* find_node(hash64_result_t hash) const
    {
        Node* cur = head_;
        while(cur)
        {
            if(hash == cur->hash)
            {
                return cur; 
            }
            cur = cur->next;
        }
        return NULL;
    }

    /**
     * @brief 找到插入位置
     *   找到小于自己hash值的最后一个节点，当前节点如果插入将被插入在该节点后面
     * @return FindPlaceResult 将在result.tar节点后面插入
     */
    FindPlaceResult find_insert_place(hash64_result_t hash)
    {
        FindPlaceResult result;
        memset(&result, 0, sizeof(result));
        Node* cur = head_;
        while(cur)
        {
            if(cur->hash < hash)
            {
                result.tar = cur;
                result.next = cur->next;
                break;
            }
            result.prev = cur;
            cur = cur->next;
        }
        return result;
    }

protected:
    Node* head_;
};
///////////////////////////////////////////////////////////////////////////////////////////////

MapDatabase::MapDatabase(std::size_t cnt, double max_load_factor)
{

}

MapDatabase::~MapDatabase()
{

}

BasicDatabase::InsertStatus 
    MapDatabase::insert(hash64_result_t hash, const char* str, std::size_t cnt)
{

}

const char* MapDatabase::lookup(hash64_result_t hash) const
{

}

void MapDatabase::rehash()
{
    
}

}; //~